﻿using System;
using System.Collections.Generic;
using CoreEx.Common.Cache;
using CoreEx.Common.Data;
using LinFu.IoC.Configuration;
using LinFu.IoC.Interfaces;

namespace CoreEx.Common.Implementation.Cache
{
    /// <summary>
    /// A <see cref="IFactory"/> class that creates <see cref="ILazyCachedValue{TValue}"/> instances.
    /// </summary>
    [Factory(typeof(ILazyCachedValue<>))]
    public class LazyCachedValueFactory : IFactory
    {
        private static readonly IDictionary<SurrogateKey, object> _cacheInstances
            = new Dictionary<SurrogateKey, object>();


        /// <summary>
        /// Creates a service instance using the given <see cref="T:LinFu.IoC.Interfaces.IFactoryRequest"/> instance.
        /// </summary>
        /// <param name="request">The <see cref="T:LinFu.IoC.Interfaces.IFactoryRequest"/> instance that describes the requested service.</param>
        /// <returns>
        /// An object instance that represents the service to be created. This cannot be <c>null</c>.
        /// </returns>
        public object CreateInstance(IFactoryRequest request)
        {
            lock (_cacheInstances)
            {
                SurrogateKey surrogateKey;
                if (string.IsNullOrEmpty(request.ServiceName))
                    surrogateKey = new SurrogateKey(new object[] { request.ServiceType });
                else
                    surrogateKey = new SurrogateKey(new object[] { request.ServiceType, request.ServiceName });
                if (!_cacheInstances.ContainsKey(surrogateKey))
                {
                    var genericTypes = request.ServiceType.GetGenericArguments();
                    var type = typeof(LazyCachedValue<>).MakeGenericType(genericTypes);
                    var instance = (ILifeSpan)Activator.CreateInstance(type);
                    instance.LifeSpan = TimeSpan.Zero;
                    _cacheInstances.Add(surrogateKey, instance);
                }
                return _cacheInstances[surrogateKey];
            }
        }
    }
}
